package com.zyx.xunyilu.controller;

import com.zyx.xunyilu.config.jwt.JWTUtils;
import com.zyx.xunyilu.entity.User;
import com.zyx.xunyilu.enums.RegisterStatus;
import com.zyx.xunyilu.service.UserService;
import com.zyx.xunyilu.utils.CacheUtils;
import com.zyx.xunyilu.utils.CodeDesUtils;
import com.zyx.xunyilu.utils.EmailUtils;
import com.zyx.xunyilu.utils.RestResponse;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authz.annotation.RequiresRoles;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import java.util.HashMap;

/**
 * @ClassName: UserController
 * @author: zyx
 * @E-mail: 1377631190@qq.com
 * @DATE: 2019/11/11 13:57
 */
@CrossOrigin
@Slf4j
@RestController
@RequestMapping("/user")
public class UserController {

    private String host;
    private final JWTUtils jwtUtils;
    private final UserService userService;
    private final EmailUtils emailUtils;
    private final CacheUtils cacheUtils;

    @Autowired
    public UserController(JWTUtils jwtUtils, UserService userService, EmailUtils emailUtils, CacheUtils cacheUtils) {
        this.jwtUtils = jwtUtils;
        this.userService = userService;
        this.emailUtils = emailUtils;
        this.cacheUtils = cacheUtils;
    }

    @ModelAttribute
    public void setToken(HttpServletRequest request,
                         @RequestHeader(value = "token", required = false, defaultValue = "") String headerToken,
                         @RequestParam(value = "token", required = false) String pToken) {
        StringBuffer requestURL = request.getRequestURL();
        int i = requestURL.indexOf("/", 8);
        if (i != -1) {
            host = requestURL.substring(0, i);
        } else {
            host = String.valueOf(requestURL);
        }
        String token = headerToken;
        if (StringUtils.isEmpty(token)) {
            token = pToken;
        }
        request.setAttribute("token", token);
    }

    @PostMapping("/register")
    public RestResponse register(User user) {
        if (userService.findUserByName(user.getName()) != null) {
            return RestResponse.fail("用户名已经使用!");
        }
        User register = userService.register(user);
        if (register != null) {
            return RestResponse.ok(register);
        }
        return RestResponse.fail("注册失败");
    }

    @PostMapping("/login")
    public RestResponse login(User user) {
        try {
            if (userService.login(user)) {
                String sign = jwtUtils.sign(user.getName(), user.getPassword());
                User userByName = userService.findUserByName(user.getName())
                        .clearUser().setToken(sign);
                return RestResponse.ok(userByName);
            }
        } catch (AuthenticationException e) {
            return RestResponse.fail("登录失败: " + e.getMessage());
        }
        return RestResponse.fail("登录失败!");
    }

    /**
     * 通过邮箱注册
     * 邮箱验证链接 5 分钟失效
     *
     * @param user 注册用户信息
     * @throws Exception name加密异常
     */
    @PostMapping("/email/register")
    public RestResponse emailRegister(@Valid User user) throws Exception {
        User register = null;
        if (StringUtils.isEmpty(user.getName())) {
            return RestResponse.fail("用户名不能为空！");
        }
        if (userService.findUserByName(user.getName()) != null) {
            return RestResponse.fail("用户名被占用！");
        }
        if (!userService.checkEmail(user.getEmail())) {
            return RestResponse.fail("邮箱已被占用！");
        }

        try {
            register = userService.register(user);
            if (register != null) {
                String code = CacheUtils.randomKey();
                cacheUtils.put5("code", code);
                emailUtils.regEmail(register.getEmail(), register, host + "/email/auth?s=" + CodeDesUtils.encryption(String.valueOf(register.getName()))
                        + "&t=" + CodeDesUtils.encryption(register.getEmail())
                        + "&code=" + code);
            } else {
                return RestResponse.fail("注册失败！");
            }
        } catch (Exception e) {
            log.error("{} -加密异常", register);
            throw e;
        }
        return RestResponse.ok(register);
    }

    /**
     * 删除用户API
     *
     * @param user 待删除的用户
     * @return 返回删除成功或失败
     */
    @PostMapping("/delete")
    public RestResponse deleteUser(User user,
                                   @RequestAttribute("token") String token) {
        String username = jwtUtils.getUsername(token);
        User userByName = userService.findUserByName(username);
        if (!userByName.getId().equals(user.getId())) {
            log.error("{} -尝试删除别人!", userByName);
            return RestResponse.fail("不能删除别人!");
        }
        User deleteUser = userService.deleteUserById(user.getId());
        if (deleteUser == null) {
            log.error("{} -删除失败!", user);
            return RestResponse.fail("删除失败!");
        }
        log.info("{} -删除成功!", deleteUser);
        return RestResponse.ok(deleteUser);
    }

    @PostMapping("/update")
    public RestResponse updateUser(User user,
                                   @RequestAttribute("token") String token) {
        String username = jwtUtils.getUsername(token);
        User userByName = userService.findUserByName(username);
        // 数据清洗,防止用户更新重要信息
        user.setPassword(null).setRegister(RegisterStatus.IS_REGISTER).setOpenId(null).setStatus(null)
            .setSolt(null).setAdmin(null).setTime(null).setEmail(null);
        if (!userByName.getId().equals(user.getId())) {
            log.error("{} -尝试更新别人!", userByName);
            return RestResponse.fail("不能更新别人!");
        }
        User updateUser = userService.updateUserById(user);
        if (updateUser == null) {
            log.error("{} -更新失败!", user);
            return RestResponse.fail("更新失败!");
        }
        log.info("{} -更新成功!", updateUser);
        return RestResponse.ok(updateUser);
    }

    @PostMapping("/change/password")
    public RestResponse changePassword(@RequestParam("password") String password,
                                       @RequestAttribute("token") String token) {
        User user = userService.updatePassword(token, password);
        if (user == null) {
            log.error("{} -尝试修改密码失败!", token);
            return RestResponse.fail("修改失败");
        }
        log.info("{} -修改密码成功", user.getName());
        return RestResponse.ok(user);
    }

    @GetMapping("/test")
    public RestResponse test(@RequestAttribute("token") String token) {
        System.out.println(host);
        String username = jwtUtils.getUsername(token);
        User user = userService.findUserByName(username);
        HashMap<String, Object> payload = new HashMap<>();
        payload.put("token", token);
        payload.put("user", user);
        return RestResponse.ok(payload);
    }

    @GetMapping("/test/admin")
    @RequiresRoles("admin")
    public RestResponse admin(@RequestAttribute("token") String token) {
        return RestResponse.ok(token);
    }

}
